package za.org.jcicada.cfgmngr.impl;

import java.net.URI;

import za.org.jcicada.cfgmngr.IConfigurationClient;
import za.org.jcicada.cfgmngr.IConfigurationServer;
import za.org.jcicada.cfgmngr.IPhysicalServer;
import za.org.jcicada.cfgmngr.ISystemSubject;
import za.org.jcicada.cfgmngr.SystemSetType;
import za.org.jcicada.cfgmngr.messages.DeregisterServiceReply;
import za.org.jcicada.cfgmngr.messages.DeregisterServiceRequest;
import za.org.jcicada.cfgmngr.messages.DeregisterSystemReply;
import za.org.jcicada.cfgmngr.messages.DeregisterSystemRequest;
import za.org.jcicada.cfgmngr.messages.GetConfigurationReply;
import za.org.jcicada.cfgmngr.messages.GetConfigurationRequest;
import za.org.jcicada.cfgmngr.messages.LocateServiceReply;
import za.org.jcicada.cfgmngr.messages.LocateServiceRequest;
import za.org.jcicada.cfgmngr.messages.RegisterServiceReply;
import za.org.jcicada.cfgmngr.messages.RegisterServiceRequest;
import za.org.jcicada.cfgmngr.messages.RegisterSystemReply;
import za.org.jcicada.cfgmngr.messages.RegisterSystemRequest;
import za.org.jcicada.cfgmngr.messages.SensorSetReply;
import za.org.jcicada.cfgmngr.messages.SensorSetRequest;
import za.org.jcicada.cfgmngr.messages.ServiceSetReply;
import za.org.jcicada.cfgmngr.messages.ServiceSetRequest;
import za.org.jcicada.cfgmngr.messages.SystemSetReply;
import za.org.jcicada.cfgmngr.messages.SystemSetRequest;
import za.org.jcicada.comms.IConnector;
import za.org.jcicada.comms.exceptions.CommsException;
import za.org.jcicada.comms.impl.MessageListenerBase;
import za.org.jcicada.comms.impl.ProxyBase;
import za.org.jcicada.genss.ServiceURN;
import za.org.jcicada.genss.SystemURN;

/**
 * IConfigurationServer implementation that proxies requests through to a remote
 * configuration server.
 */
public class ConfigurationServerProxy extends ProxyBase<IConfigurationClient> implements IConfigurationServer {

    /**
     * Constructor passes connector to base class
     * 
     * @param connector connector used for creating connections
     * @throws CommsException
     */
    public ConfigurationServerProxy(IConnector connector) {
        super(connector);
    }

    /**
     * Create a ConfigurationServerProxy.
     * 
     * @param locationURI address of the acceptor
     */
    public ConfigurationServerProxy(URI locationURI) {
        super(locationURI);
    }

    @Override
    protected MessageListenerBase createReceiver(IConfigurationClient client) {
        return new Receiver(client);
    }

    public ISystemSubject getSystemSubject() {
    	throw new IllegalStateException("Can't get system subject from proxy object");
    }
    
    public IPhysicalServer getPhysicalServer() {
    	throw new IllegalStateException("Can't get physical server from proxy object");
    }
    
    public void requestDeregisterService(IConfigurationClient client, URI locationURI, ServiceURN serviceURN) {
        sendMessage(client, new DeregisterServiceRequest(locationURI, serviceURN));
    }

    public void requestGetConfiguration(IConfigurationClient client, SystemURN systemURN) {
        sendMessage(client, new GetConfigurationRequest(systemURN));
    }

    public void requestLocateService(IConfigurationClient client, ServiceURN serviceURN, String protocol) {
        sendMessage(client, new LocateServiceRequest(serviceURN, protocol));
    }

    public void requestRegisterService(IConfigurationClient client, URI locationURI, ServiceURN serviceURN) {
        sendMessage(client, new RegisterServiceRequest(locationURI, serviceURN));
    }

    public void requestDeregisterSystem(IConfigurationClient client, SystemURN systemURN) {
        sendMessage(client, new DeregisterSystemRequest(systemURN));
    }

    public void requestRegisterSystem(IConfigurationClient client, SystemURN systemURN) {
        sendMessage(client, new RegisterSystemRequest(systemURN));
    }

    public void requestSystemSet(IConfigurationClient client, SystemSetType type) {
        sendMessage(client, new SystemSetRequest(type));
    }

    public void requestSensorSet(IConfigurationClient client, SystemURN systemURN) {
        sendMessage(client, new SensorSetRequest(systemURN));
    }
    
    public void requestServiceSet(IConfigurationClient client, SystemURN systemURN) {
    	sendMessage(client, new ServiceSetRequest(systemURN));
    }

    /**
     * Implementation of IMessageListener that dispatches messages to an
     * IConfigurationClient.
     */
    public class Receiver extends MessageListenerBase {

        /**
         * Handle to callback object for messages from the subject to the
         * client.
         */
        IConfigurationClient client;

        public Receiver(IConfigurationClient client) {
            this.client = client;
        }

        public void onClose() throws Exception {
            client.informDisconnect();
        }

        // dispatch methods

        public void cfgmngrDeregisterServiceReply(DeregisterServiceReply msg) {
            client.replyDeregisterService(msg.getResult(), msg.getLocationURI(), msg.getServiceURN());
        }

        public void cfgmngrGetConfigurationReply(GetConfigurationReply msg) {
            client.replyGetConfiguration(msg.getResult(), msg.getConfiguration());
        }

        public void cfgmngrLocateServiceReply(LocateServiceReply msg) {
            client.replyLocateService(msg.getResult(), msg.getServiceURN(), msg.getLocationURI());
        }

        public void cfgmngrRegisterServiceReply(RegisterServiceReply msg) {
            client.replyRegisterService(msg.getResult(), msg.getLocationURI(), msg.getServiceURN());
        }

        public void cfgmngrDeregisterSystemReply(DeregisterSystemReply msg) {
            client.replyDeregisterSystem(msg.getResult(), msg.getSystemURN());
        }

        public void cfgmngrRegisterSystemReply(RegisterSystemReply msg) {
            client.replyRegisterSystem(msg.getResult(), msg.getSystemURN(), msg.getReregister());
        }

        public void cfgmngrSystemSetReply(SystemSetReply msg) {
            client.replySystemSet(msg.getResult(), msg.getType(), msg.getSystemURNs());
        }

        public void cfgmngrSensorSetReply(SensorSetReply msg) {
            client.replySensorSet(msg.getResult(), msg.getSystemURN(), msg.getSensorURNs());
        }
        
        public void cfgmngrServiceSetReply(ServiceSetReply msg) {
        	client.replyServiceSet(msg.getResult(), msg.getSystemURN(), msg.getServiceURNs());
        }
    }

}
